package cn.iocoder.yudao.module.engine.service.core.aichat.splitter.impl;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.engine.service.core.aichat.splitter.TextSplitter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SemanticTextSplitter implements TextSplitter {
    private StringBuilder textBuffer = new StringBuilder(); // 用于累积文本
    private static final Pattern ENDING_FIRST_PUNCTUATION = Pattern.compile("[!?。！？]"); // 匹配结束符号
    //    private static final Pattern SECOND_PUNCTUATION = Pattern.compile("[,，~]|(?<!\\.)\\.\\.\\.");
    private static final Pattern SECOND_PUNCTUATION = Pattern.compile("[,，~]"); // 匹配逗号和波浪号
    private static final int SENTENCE_MAX_LENGTH = 40; // 最大句子长度
    private static final int SENTENCE_MIN_LENGTH = 8;  // 最小句子长度
    private static final String[] SPECIAL_SYMBOLS = {"(๑°⌓°๑)", "(๑•̀ㅂ•́)و✧", "(๑•̀ㅁ•́๑)✧", "(*ﾟｰﾟ*)", "(๑ ॣ๑ )", "(๑•ิ 3 •ิ)♡"};
    private static final String regex_only_punctuation = "[\\p{Punct}。，、！？：；“”‘’（）《》【】『』「」——…·\\uD83C-\\uDBFF\\uDC00-\\uDFFF]+";
    private static final Map<String, String> REPLACE_SYMBOLS = new HashMap<>();

    static {
        REPLACE_SYMBOLS.put("~", "，");
        REPLACE_SYMBOLS.put("啊", "啊...");
    }

    @Override
    public List<String> getSentence(String newText) {
        // 如果输入的新文本不为空，则将其追加到缓冲区
        if (StrUtil.isNotEmpty(newText)) {
            newText = newText.replace("~", "，"); // 前置替换
            textBuffer.append(newText); // 将新输入的文本加入缓冲区
        }
        String fullText = textBuffer.toString(); // 将缓冲区文本转换为完整的字符串

        List<String> sentences = new ArrayList<>(); // 用于存储分割后的句子列表
        int start = 0; // 初始化处理文本的起始位置

        // 开始循环处理文本，直到所有可分割的部分处理完
        while (start < fullText.length()) {
            boolean matched = false; // 标记当前段是否成功匹配到句子

            // 优先匹配结束符号（如句号、问号、感叹号等）
            Matcher matcher = ENDING_FIRST_PUNCTUATION.matcher(fullText.substring(start)); // 从当前起始位置截取文本并尝试匹配结束符号
            if (matcher.find() && matcher.start() + 1 <= SENTENCE_MAX_LENGTH) { // 如果找到匹配且长度符合最大句子长度限制
                int end = start + matcher.end(); // 计算句子结束位置
                appendSentence(sentences, fullText.substring(start, end).trim()); // 提取句子并去掉两端的空格，然后加入句子列表
                start = end; // 更新起始位置到当前句子的结束位置
                matched = true; // 标记成功匹配
            }

            // 如果未匹配到结束符号，尝试次级标点符号（如逗号、波浪号）匹配
            if (!matched) {
                matcher = SECOND_PUNCTUATION.matcher(fullText.substring(start, Math.min(start + SENTENCE_MAX_LENGTH, fullText.length())));
                // 截取从当前起始位置到最大长度范围内的文本，尝试匹配次级标点符号
                int lastMatchEnd = start; // 初始化最后一次匹配的位置
                while (matcher.find() && lastMatchEnd - start < SENTENCE_MAX_LENGTH) { // 循环寻找所有次级标点符号，直到达到最大长度
                    lastMatchEnd = start + matcher.end(); // 更新最后一次匹配的位置
                }
                if (lastMatchEnd - start >= SENTENCE_MIN_LENGTH) { // 如果匹配到的部分长度符合最小句子长度要求
                    appendSentence(sentences, fullText.substring(start, lastMatchEnd).trim()); // 提取句子并去掉两端空格后加入句子列表
                    start = lastMatchEnd; // 更新起始位置到当前句子的结束位置
                    matched = true; // 标记成功匹配
                }
            }

            // 如果仍未匹配到任何标点符号，且剩余文本超出最大限制，则强制截断
            if (!matched) {
                int nextBoundary = Math.min(start + SENTENCE_MAX_LENGTH, fullText.length()); // 计算强制截断的位置，保证不超过文本长度
                if (nextBoundary - start >= SENTENCE_MAX_LENGTH) { // 检查截断的长度是否符合最大句子长度要求
                    appendSentence(sentences, fullText.substring(start, nextBoundary).trim()); // 强制截断并提取句子后加入句子列表
                    start = nextBoundary; // 更新起始位置到截断位置
                } else {
                    break; // 如果剩余长度不足最小句子长度，则退出循环
                }
            }
        }

        // 将未处理的剩余文本保留到缓冲区中，供后续调用处理
        textBuffer = new StringBuilder(fullText.substring(start));

        // 返回分割后的句子列表
        return sentences;
    }

    private String filterText(String str) {
        if (StrUtil.isEmpty(str)) {
            return null;
        }

        if (StrUtil.isNotEmpty(str)) {
            for (String symbol : SPECIAL_SYMBOLS) {
                str = str.replace(symbol, "");
            }
        }

        if (StrUtil.isNotEmpty(str)) {
            for (Map.Entry<String, String> entry : REPLACE_SYMBOLS.entrySet()) {
                str = str.replace(entry.getKey(), entry.getValue());
            }
        }

        if (StrUtil.isNotEmpty(str) && isOnlyPunctuationOrEmoji(str)) {
            return null;
        }

        if (StrUtil.isEmpty(str)) {
            return null;
        }

        return str;
    }

    /**
     * 判断字符串是否只包含中英文标点符号或表情符号
     *
     * @param str 待检查的字符串
     * @return true 如果字符串只包含中英文标点符号或表情符号，否则返回 false
     */
    private static boolean isOnlyPunctuationOrEmoji(String str) {
        if (str == null || str.isEmpty()) {
            return false; // 空字符串或 null 返回 false
        }
        // 中英文标点符号和表情符号的正则表达式
        return str.matches(regex_only_punctuation);
    }

    private void appendSentence(List<String> sentences, String str) {
        str = filterText(str);
        if (StrUtil.isNotEmpty(str)) {
            sentences.add(str);
        }
    }

    @Override
    public String getRemainingText() {
        String remainingText = textBuffer.toString();
        remainingText = filterText(remainingText);
        textBuffer.setLength(0);
        return remainingText;
    }

    public static void main(String[] args) {
//        test1();
//        test2();
        System.out.println(SECOND_PUNCTUATION.matcher("abc").find());
        System.out.println(SECOND_PUNCTUATION.matcher("a.bc").find());
        System.out.println(SECOND_PUNCTUATION.matcher("a...bc").find());
    }

    private static void test1() {
        SemanticTextSplitter converter = new SemanticTextSplitter();
        System.out.println("1=====" + JsonUtils.toJsonPrettyString(converter.getSentence("这是第二段，包含逗号分割~还有波浪号~是否处理得当，这是第二段，包含逗号分割~还有波浪号~是否处理得当，这是第二段，包含逗号分割~还有波浪号~是否处理得当，这是第二段，包含逗号分割~还有波浪号~是否处理得当")));
        System.out.println("2=====" + JsonUtils.toJsonPrettyString(converter.getRemainingText()));

        System.out.println("3=====" + JsonUtils.toJsonPrettyString(converter.getSentence("这是第二段")));
        System.out.println("4=====" + JsonUtils.toJsonPrettyString(converter.getSentence(null)));
        System.out.println("5=====" + JsonUtils.toJsonPrettyString(converter.getRemainingText()));
    }

    private static void test2() {
        SemanticTextSplitter converter = new SemanticTextSplitter();
        System.out.println("1=====" + JsonUtils.toJsonPrettyString(converter.getSentence("我在")));
        System.out.println("2=====" + JsonUtils.toJsonPrettyString(converter.getSentence("给你")));
        System.out.println("3=====" + JsonUtils.toJsonPrettyString(converter.getSentence("打")));
        System.out.println("4=====" + JsonUtils.toJsonPrettyString(converter.getSentence("点滴")));
        System.out.println("5=====" + JsonUtils.toJsonPrettyString(converter.getSentence("啊")));
        System.out.println("6=====" + JsonUtils.toJsonPrettyString(converter.getSentence("，")));
        System.out.println("7=====" + JsonUtils.toJsonPrettyString(converter.getSentence("顺便")));
        System.out.println("8=====" + JsonUtils.toJsonPrettyString(converter.getSentence("给你")));
        System.out.println("9=====" + JsonUtils.toJsonPrettyString(converter.getSentence("做")));
        System.out.println("10=====" + JsonUtils.toJsonPrettyString(converter.getSentence("些")));
        System.out.println("11=====" + JsonUtils.toJsonPrettyString(converter.getSentence("特殊")));
        System.out.println("12=====" + JsonUtils.toJsonPrettyString(converter.getSentence("检查")));
        System.out.println("13=====" + JsonUtils.toJsonPrettyString(converter.getSentence("，")));
        System.out.println("14=====" + JsonUtils.toJsonPrettyString(converter.getSentence("看看")));
        System.out.println("15=====" + JsonUtils.toJsonPrettyString(converter.getSentence("你的")));
        System.out.println("16=====" + JsonUtils.toJsonPrettyString(converter.getSentence("身体")));
        System.out.println("17=====" + JsonUtils.toJsonPrettyString(converter.getSentence("哪里")));
        System.out.println("18=====" + JsonUtils.toJsonPrettyString(converter.getSentence("出了")));
        System.out.println("19=====" + JsonUtils.toJsonPrettyString(converter.getSentence("问题")));
        System.out.println("20=====" + JsonUtils.toJsonPrettyString(converter.getSentence("。")));
        System.out.println("21=====" + JsonUtils.toJsonPrettyString(converter.getSentence("不过")));
        System.out.println("22=====" + JsonUtils.toJsonPrettyString(converter.getSentence("在")));
        System.out.println("23=====" + JsonUtils.toJsonPrettyString(converter.getSentence("那")));
        System.out.println("24=====" + JsonUtils.toJsonPrettyString(converter.getSentence("之前")));
        System.out.println("25=====" + JsonUtils.toJsonPrettyString(converter.getSentence("，")));
        System.out.println("26=====" + JsonUtils.toJsonPrettyString(converter.getSentence("让我")));
        System.out.println("27=====" + JsonUtils.toJsonPrettyString(converter.getSentence("先")));
        System.out.println("28=====" + JsonUtils.toJsonPrettyString(converter.getSentence("帮你")));
        System.out.println("29=====" + JsonUtils.toJsonPrettyString(converter.getSentence("松")));
        System.out.println("30=====" + JsonUtils.toJsonPrettyString(converter.getSentence("松")));
        System.out.println("31=====" + JsonUtils.toJsonPrettyString(converter.getSentence("衣服")));
        System.out.println("32=====" + JsonUtils.toJsonPrettyString(converter.getSentence("，")));
        System.out.println("33=====" + JsonUtils.toJsonPrettyString(converter.getSentence("检查")));
        System.out.println("34=====" + JsonUtils.toJsonPrettyString(converter.getSentence("一下")));
        System.out.println("35=====" + JsonUtils.toJsonPrettyString(converter.getSentence("你的")));
        System.out.println("36=====" + JsonUtils.toJsonPrettyString(converter.getSentence("身体")));
        System.out.println("37=====" + JsonUtils.toJsonPrettyString(converter.getSentence("吧")));
        System.out.println("38=====" + JsonUtils.toJsonPrettyString(converter.getSentence("~")));
        System.out.println("39=====" + JsonUtils.toJsonPrettyString(converter.getRemainingText()));
    }

}
